package buzzword;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import json.JSONArray;
import json.JSONException;
import json.JSONObject;

public class Client implements ClientFunctions {

	private String playerName;
	private int gameID = -1;
	private Board gameBoard = null;

	public Client(String playerName) {
		this.playerName = playerName;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#startGame()
	 */
	public boolean startGame() throws NoGameHostException, JSONException,
			ServerCommunicationException, GameEndedException {
		final String urlExtension = "start?gameid=" + gameID + "&player="
				+ playerName;
		JSONObject starterMsg = new JSONObject(getJSON(urlExtension));
		if (starterMsg.getString("status").equals("error"))
			throw new NoGameHostException();
		else {
			this.get();
			return true;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#bingo()
	 */
	public boolean bingo() throws JSONException {
		final String urlExtension = "bingo?gameid=" + gameID + "&player="
				+ playerName;
		return new JSONObject(getJSON(urlExtension)).getString("status")
				.equals("won");

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#getBoardFields()
	 */
	public List<Field> getBoardFields() throws NoGameFoundException,
			GameNotStartetException, JSONException,
			ServerCommunicationException, GameEndedException {
		if (this.gameBoard == null)
			throw new NoGameFoundException();
		else if (this.get().equals("wait"))
			throw new GameNotStartetException();
		else if (this.get().equals("won") || this.get().equals("lost")) {
			throw new GameEndedException();
		} else
			return this.gameBoard.getFields();

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#getDrawnWords()
	 */
	public List<String> getDrawnWords() throws JSONException,
			ServerCommunicationException, GameNotStartetException, GameEndedException {
		if (this.get().equals("wait"))
			throw new GameNotStartetException();
		return this.gameBoard.getWords();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#joinGame(int)
	 */
	public void joinGame(int gameID) throws JSONException,
			ServerCommunicationException, GameEndedException {
		this.gameID = gameID;
		this.gameBoard = new Board();
		this.get();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#createGame(int, int, java.lang.String)
	 */
	public void createGame(int columns, int rows, String category,
			String gameTitle) throws JSONException {
		final String urlExtension = "new?title=" + gameTitle + "&player="
				+ playerName + "&category=" + category + "&rows=" + rows
				+ "&columns=" + columns;
		JSONObject currentGame = new JSONObject(getJSON(urlExtension));
		System.out.println(currentGame);
		this.gameID = currentGame.getInt("gameid");
		this.gameBoard = new Board();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#getWordsInDB(java.lang.String)
	 */
	public List<String> getWordsInDB(String category) throws JSONException {
		final String urlExtension = "words?category=" + category;
		String JSONWords = getJSON(urlExtension);
		return new WordList().getWords(JSONWords);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#getGames()
	 */
	public List<Game> getGames() throws JSONException {
		final String urlExtension = "list";
		List<Game> currentGames = new ArrayList<Game>();
		JSONObject games = new JSONObject(getJSON(urlExtension));
		JSONArray gameArray = games.getJSONArray("games");
		for (int i = 0; i < gameArray.length(); i++) {
			currentGames.add(new Game(gameArray.getJSONObject(i)));
		}

		return currentGames;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#setPlayerName(java.lang.String)
	 */
	public void setPlayerName(String newName) {
		this.playerName = newName;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see buzzword.ClientFunctions#getPlayerName()
	 */
	public String getPlayerName() {
		return this.playerName;
	}

	public int[] getBoardSizes() {
		int[] values = new int[2];
		if (this.gameBoard == null)
			return null;
		else {
			values[0] = this.gameBoard.getRows();
			values[1] = this.gameBoard.getColumns();
			return values;
		}

	}

	private String get() throws JSONException, ServerCommunicationException, GameEndedException {
		final String urlExtension = "get?gameid=" + gameID + "&player="
				+ playerName;
		JSONObject getter = new JSONObject(getJSON(urlExtension));
		if (getter.getString("status").equals("error"))
			throw new ServerCommunicationException();
		if (getter.getString("status").equals("won")
				|| getter.getString("status").equals("lost"))
			throw new GameEndedException();
		return gameBoard.get(gameID, playerName, getter);

	}

	private String getJSON(String urlExtension) {
		final String baseAdress = "http://4c0.de/bingo/service/";
		InputStream input = null;
		try {
			URL option = new URL(baseAdress + urlExtension);
			input = option.openStream();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return getURLString(input);

	}

	private String getURLString(InputStream input) {
		Scanner in = new Scanner(input);
		String content = "";
		while (in.hasNext()) {
			content += in.next();
		}
		return content;
	}

}
